# 什么是迭代器?什么是生成器?两者有什么区别?
# 概念上: 迭代器可以用来表示一个数据流, 提供了数据的惰性返回功能(只有我们主动去使用next方法调用, 才会返回值)
# 实现了__next__接口的对象


# 协程的实现原理
# 协程的实现原理就是生成器的实现原理,在生成器的基础上又提供了传递值的功能
# 通过send方法向生成器传递值,对生成器进行send操作一定要调用next方法预激, 使其停留在第一个yield位置

# asyncio（异步）实现原理：自动维护了一个事件队列, 然后循环访问事件来完成异步的消息维护

# 用协程实现一个计算平均数的函数
def coro_avg():
    total = 0
    length = 0
    while True:
        try:
            value = yield total/length
        except ZeroDivisionError:
            total += yield 0
            length += 1
my_avg = coro_avg()
print(next(my_avg))
print(my_avg.send(1))
print(my_avg.send(10))


# 编写一个asyncio异步程序
import asyncio
import time

class Response:
    staus_code = 50

async def sim_request(index):
    print(f"模拟发送请求 Index: {index}")
    response = Response()
    # 模拟网络延迟
    # 当前是单线程运行的, 如果调用的是time.sleep(2), 那么这个线程会被阻塞
    # 当前线程被阻塞之后, 不会让渡cpu资源, 异步的效率就不会体现
    await asyncio.sleep(2)
    print(f"request index {index}, response status_code: {response.staus_code}")
    return response.staus_code

loop = asyncio.get_event_loop()  # 获取消息队列

task_array = []  # 包装任务
for i in range(100):
    task_array.append(sim_request(i))

loop.run_until_complete(asyncio.wait(task_array))  # 循环访问事件来完成异步的消息维护

loop.close()  # 关闭事件循环

# 扩展:了解aiohttp异步请求网址